/*This file is part of WZLibCP.

 *  WZLibCP is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

 *  WZLibCP is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
    along with WZLibCP.  If not, see <http://www.gnu.org/licenses/>.
		
	Author: calc0000
*/
#include "stdafx.h"
#include "WZLibUtils.h"

#include "zlib.h"

using namespace std;

namespace WZLib{
	string	WZConfig::imagePath="";
	string	WZConfig::imageDir="";
	string	WZConfig::wzSearchDir="";
};

string getFileName(string path){
	for(int i=(path.size()-1);i>=0;i--){
		if(path.at(i)=='\\' || path.at(i)=='/')
			return path.substr(i+1,path.size()-i-1);
	}
	return path;
}

string getDirName(string path){
	for(int i=(path.size()-1);i>=0;i--){
		if(path.at(i)=='\\' || path.at(i)=='/')
			return path.substr(0,i);
	}
	return ".";
}

string lower(string s){
	string ret;
	for(unsigned int i=0;i<s.size();i++){
		if(s.at(i)>=65 && s.at(i)<=90)
			ret+=(s.at(i)+32);
		else
			ret+=s.at(i);
	}
	return ret;
}

std::vector<std::string> tokenize(std::string str,std::string del,bool dropEmpty){
	std::vector<std::string> ret;
	unsigned int i=0,j=0;
	for(unsigned int l=str.size();i<l;i++){
		if(del.find(str[i])!=std::string::npos){
			std::string sub=str.substr(j,i-j);
			if(!(dropEmpty && sub.size()==0))
				ret.push_back(str.substr(j,i-j));
			j=i+1;
		}
	}
	std::string sub=str.substr(j,str.size()-j);
	if(!(dropEmpty && sub.size()==0))
		ret.push_back(str.substr(j,str.size()-j));
	return ret;
}

int z_decompress(unsigned char* inBuffer,int inLen,unsigned char** outBufferPtr,int* outLen){ //returns out buffer, len outLen
	const int inChunk=1024;
	const int outChunk=1024;
	unsigned char* outData=(unsigned char*)malloc(sizeof(unsigned char)*outChunk);
	unsigned char* outBuffer=(unsigned char*)malloc(sizeof(unsigned char)*1);
	int outBufferIndex=0;
	int inBufferIndex=0;
	int outDataLen=0;
	int err=Z_OK;
	z_stream strm;
	{
		strm.next_in=NULL;
		strm.avail_in=0;
		strm.opaque=NULL;
		strm.zfree=Z_NULL;
		strm.zalloc=Z_NULL;
		inflateInit(&strm);
		
		do{
			strm.next_in=inBuffer+sizeof(unsigned char)*inBufferIndex;
			strm.avail_in=(inLen-inBufferIndex > inChunk)?inChunk:inLen-inBufferIndex;
			if(strm.avail_in==0)
				break;
			inBufferIndex+=strm.avail_in;
			do{
				if(strm.avail_in==0)
					break;
				strm.avail_out=outChunk;
				strm.next_out=outData;
				err=inflate(&strm,Z_NO_FLUSH);
				switch(err){
					case Z_NEED_DICT:
					case Z_DATA_ERROR:
					case Z_MEM_ERROR:
					case Z_BUF_ERROR:
						free(outData);
						inflateEnd(&strm);
						return err;
				}
				int have=outChunk-strm.avail_out;
				outBuffer=(unsigned char*)realloc(outBuffer,sizeof(unsigned char*)*strm.total_out);
				memcpy((void*)(outBuffer+(sizeof(unsigned char)*outBufferIndex)),(void*)outData,have);
				outBufferIndex+=have;
			}while(strm.avail_out==0);
		}while(err!=Z_STREAM_END);
		
		inflateEnd(&strm);
	}
	*outLen=strm.total_out;
	*outBufferPtr=outBuffer;
	free(outData);
	return Z_OK;
}

int z_compress(unsigned char* inBuffer,int inLen,int level,unsigned char** outBufferPtr,int* outLen){
	const int inChunk=1024;
	const int outChunk=1024;
	unsigned char* outData=(unsigned char*)malloc(sizeof(unsigned char)*outChunk);
	unsigned char* outBuffer=(unsigned char*)malloc(sizeof(unsigned char)*1);
	int outBufferIndex=0;
	int inBufferIndex=0;
	int outDataLen=0;
	int err=Z_OK;
	z_stream strm;
	{
		strm.next_in=NULL;
		strm.avail_in=0;
		strm.opaque=NULL;
		strm.zfree=Z_NULL;
		strm.zalloc=Z_NULL;
		err=deflateInit(&strm,level);
		
		if(err!=Z_OK){
			free(outData);
			deflateEnd(&strm);
			return err;
		}
		
		strm.next_in=inBuffer;
		strm.avail_in=inLen;
		int dataLen=deflateBound(&strm,inLen);
		outBuffer=(unsigned char*)malloc(sizeof(unsigned char)*dataLen);
		strm.next_out=outBuffer;
		strm.avail_out=dataLen;
		
		do{
			err=deflate(&strm,Z_FINISH);
			if(err!=Z_OK && err!=Z_STREAM_END){
				free(outData);
				deflateEnd(&strm);
				return err;
			}
		}while(err!=Z_STREAM_END);
		
		deflateEnd(&strm);
	}
	*outLen=strm.total_out;
	*outBufferPtr=outBuffer;
	free(outData);
	return Z_OK;
}